local status_lsp_ok, lspconfig    = pcall(require, "lspconfig")
local status_cmp_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp")
local status_ill_ok, illuminate   = pcall(require, "illuminate")

if not status_lsp_ok or not status_cmp_ok or not illuminate then
    vim.notify("lspconfig not found!")
end

local M = {}

local function lsp_keymaps(bufnr)
    vim.keymap.set("n", "gD",         '<cmd>lua vim.lsp.buf.declaration()<cr>',                    { noremap = true, silent = true, desc = "Go to declaration"})
    vim.keymap.set("n", "gd",         '<cmd>lua vim.lsp.buf.definition()<cr>',                     { noremap = true, silent = true, desc = "Go to definition" })
    vim.keymap.set("n", "gh",         '<cmd>lua vim.lsp.buf.hover()<cr>',                          { noremap = true, silent = true, desc = "Show infomation"  })
    vim.keymap.set("n", "gl",         '<cmd>lua vim.diagnostic.open_float()<cr>',                  { noremap = true, silent = true, desc = "Open diagnostic"  })
    vim.keymap.set("n", 'gr',         '<cmd>lua vim.lsp.buf.references()<cr>',                     { noremap = true, silent = true,                           }) -- gd can handler that
    vim.keymap.set("n", 'gI',         '<cmd>lua vim.lsp.buf.implementation()<cr>',                 { noremap = true, silent = true,                           })
    vim.keymap.set("n", "<leader>rn", '<cmd>lua vim.lsp.buf.rename()<cr>',                         { noremap = true, silent = true, desc = "Rename"           })
    vim.keymap.set("n", "<leader>lf", '<cmd>lua vim.lsp.buf.format{ async = true }<cr>',           { noremap = true, silent = true, desc = "Format"           })
    vim.keymap.set("n", "<leader>li", '<cmd>LspInfo<cr>',                                          { noremap = true, silent = true, desc = "Lsp info"         })
    vim.keymap.set("n", "<leader>lI", '<cmd>LspInstallInfo<cr>',                                   { noremap = true, silent = true, desc = "Lsp install info" })
    vim.keymap.set("n", '<leader>la', '<cmd>lua vim.lsp.buf.code_action()<cr>',                    { noremap = true, silent = true, desc = "Code action"      })
    vim.keymap.set("n", '<leader>lj', '<cmd>lua vim.diagnostic.goto_next({border="rounded"})<cr>', { noremap = true, silent = true, desc = "Go to next diag"  }) -- 跳转上一个
    vim.keymap.set("n", '<leader>lk', '<cmd>lua vim.diagnostic.goto_prev({border="rounded"})<cr>', { noremap = true, silent = true, desc = "Go to prev diag"  }) -- 跳转下一个
    vim.keymap.set("n", '<leader>lq', '<cmd>lua vim.diagnostic.setloclist()<cr>',                  { noremap = true, silent = true, desc = "Setloclist"       })
    vim.keymap.set("n", '<leader>ls', '<cmd>lua vim.lsp.buf.signature_help()<cr>',                 { noremap = true, silent = true,                           })
end

local function lsp_highlight_document(client)
    -- Set autocommands conditional on server_capabilities
    -- if client.resolved_capabilities.document_highlight then
    -- end
    vim.api.nvim_exec([[
        augroup lsp_document_highlight
            autocmd! * <buffer>
            autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
            autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
        augroup END
    ]], false
    )
end

M.on_attach = function(client, bufnr)
    lsp_keymaps(bufnr)
    illuminate.on_attach(client) -- lsp_highlight_document
    -- lsp_highlight_document(client)

    require("aerial").on_attach(client, bufnr)
    require("lsp_signatrue").on_attach()
end

M.capabilities = vim.lsp.protocol.make_client_capabilities()
M.capabilities = cmp_nvim_lsp.default_capabilities(M.capabilities)
M.capabilities.textDocument.completion.completionItem.snippetSupport = true

return M